package org.hbgl.geoentity.admin.aspect;

import com.alibaba.fastjson.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.hbgl.geoentity.admin.annotation.LoginLog;
import org.hbgl.geoentity.admin.shiro.LoginUser;
import org.hbgl.geoentity.admin.shiro.UserType;
import org.hbgl.geoentity.db.domain.GeUser;
import org.hbgl.geoentity.db.domain.LogLogin;
import org.hbgl.geoentity.db.service.LogService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 代码功能：
 * 开发日期：2022/4/18
 * 作者：蒋海仑
 * 联系方式：
 * 版本更迭说明：
 * 版权信息：河北广联信息技术有限公司
 */
@Aspect
@Component
@Order(1)
public class LogLoginAspect {
    private final Log logger = LogFactory.getLog(LogLoginAspect.class);

    @Resource
    private LogService logService;

    /**
     * 此处的切点是注解的方式，也可以用包名的方式达到相同的效果
     * '@Pointcut("execution(* com.wwj.springboot.service.impl.*.*(..))")'
     */
    @Pointcut("@annotation(org.hbgl.geoentity.admin.annotation.LoginLog)")
    private void loginLog() {
    }

    @Around("loginLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Object res = null;
        long time = System.currentTimeMillis();
        try {
            res = joinPoint.proceed();
            time = System.currentTimeMillis() - time;
            return res;
        } finally {
            try {
                // 方法执行完成后增加日志
                addOperationLog(joinPoint, res, time);
            } catch (Exception e) {
                logger.error("LogLoginAspect 操作失败", e);
            }
        }
    }

    private void addOperationLog(ProceedingJoinPoint joinPoint, Object res, long time) {
        LogLogin logLogin = new LogLogin();
        Map<String, Object> requestParams = BaseAspect.getRequestParamsByProceedingJoinPoint(joinPoint);
        Map args = JSON.parseObject(requestParams.get("body").toString(), Map.class);
        if (args.containsKey("username")) {
            logLogin.setUsername(args.get("username").toString());
        }
        if (args.containsKey("platform_type")) {
            logLogin.setPlatformType(args.get("platform_type").toString());
        }
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        LoginLog annotation = signature.getMethod().getAnnotation(LoginLog.class);
        if (annotation != null) {
            //获得登录用户信息
            LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            if (loginUser != null) {
                GeUser user = null;
                if (UserType.ADMIN.equals(annotation.userType())) {
                    user = loginUser.getAdminUser();
                    logLogin.setPlatformType("管理后台");
                } else if (UserType.UNIT.equals(annotation.userType())) {
                    user = loginUser.getUnitUser();
                    logLogin.setPlatformType("业务前台");
                }
                if (user != null) {
                    logLogin.setUnitId(user.getUnitId());
                    logLogin.setUserId(user.getId());
                    logLogin.setUsername(user.getUsername());
                    logLogin.setRealname(user.getRealname());
                }
            }

            Map result = JSON.parseObject(JSON.toJSONString(res), Map.class);
            if (result.containsKey("errno")) {
                logLogin.setState(Integer.parseInt(result.get("errno").toString()));
            }
            String detail = "'" + logLogin.getUsername() + "'=》" + annotation.detail();
            if (result.containsKey("errmsg")) {
                detail += "，" + result.get("errmsg").toString();
            }
            logLogin.setDetail(detail);
        }
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            logLogin.setIpAddress(request.getRemoteAddr());
        }
        logLogin.setLoginTime(LocalDateTime.now());
        logService.add(logLogin);
    }
}
